package vis.items.visualItem;

import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import processing.core.PApplet;

public abstract class VisualObject implements IVisualObject {
	protected PApplet root;
	protected IVisualObject parent = null;

	protected List<IVisualObject> children;

	protected int x;
	protected int y;
	protected int width;
	protected int height;
	protected Color color;

	protected int offsetX;
	protected int offsetY;

	public VisualObject(PApplet root, IVisualObject parent) {
		this.root = root;
		this.parent = parent;
		children = Collections.synchronizedList(new ArrayList<IVisualObject>());
		synchronizeParentPosition();
	}

	private void synchronizeParentPosition() {
		if (null != parent) {
			Point parentLocation = parent.getLocation();
			x += parentLocation.x;
			y += parentLocation.y;
		}
	}

	public VisualObject color(Color color) {
		this.color = color;
		return this;
	}

	public VisualObject at(int x, int y) {
		this.x = x;
		this.y = y;
		return this;
	}

	public Point getLocation() {
		return new Point(this.x, this.y);
	}

	public VisualObject size(int width, int height) {
		this.width = width;
		this.height = height;
		return this;
	}

	public void addChild(VisualObject component) {
		children.add(component);
	}

	public void removeChild(VisualObject component) {
		if (children.contains(component)) {
			children.remove(component);
		}
	}

	@Override
	public void update() {
		updateItself();
		updateChildren();
	}

	@Override
	public void updateItself() {
		_updateOffset();
	}

	private void _updateOffset() {
		// TODO minhvv find other solution
		if (null != parent) {
			Point parentLocation = parent.getLocation();
			offsetX = parentLocation.x;
			offsetY = parentLocation.y;
		}
	}

	@Override
	public void updateChildren() {
		if (null != children && !children.isEmpty()) {
			synchronized (children) {
				Iterator<IVisualObject> i = children.iterator();
				while (i.hasNext()) {
					IVisualObject obj = (IVisualObject) i.next();
					obj.update();
				}
			}

		}
	}

	@Override
	public void display() {
		displayItself();
		displayChildren();
	}

	@Override
	public void displayItself() {
		root.noFill();
		root.stroke(255);
		{
			root.rect(x + offsetX, y + offsetY, width, height);
			// TODO minhvv other solution?
			// root.rect(x, y, width, height);
		}
		root.noStroke();
	}

	@Override
	public void displayChildren() {
		if (null != children && !children.isEmpty()) {
			synchronized (children) {
				Iterator<IVisualObject> i = children.iterator();
				while (i.hasNext()) {
					IVisualObject obj = (IVisualObject) i.next();
					obj.display();
				}
			}

		}
	}

	public String toString() {
		return "VisualObject:{x=" + x
				+ ", y=" + y
				+ ", w=" + width
				+ ",h=" + height
				+ "}";
	}

}
